/*
 * jAutomation: Portable input Automation 
 * Copyright (C) 2012 Dominik Hensler.  
 * http://code.google.com/p/jautomation
 * 
 * This Program uses JNativeHook by Alexander Barker:
 * JNativeHook: Global keyboard and mouse hooking for Java.
 * Copyright (C) 2006-2012 Alexander Barker.  All Rights Received.
 * http://code.google.com/p/jnativehook/
 *
 * 
 * This file is part of JAutomation.

 * JAutomation is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.

 * JAutomation is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with JAutomation.  If not, see <http://www.gnu.org/licenses/>.
 */
package org.jautomation.pdetect;

import java.awt.Color;
import java.awt.image.BufferedImage;

/**
 *
 * @author Dominik Hensler
 * 
 * After a lot of experimenting color comparisons turned out to be
 * much easier in CIElab space then in sRGB.
 * 
 *
 * 
 * This is an adaptation of the pseudocode found at easyrgb.com
 * It works, but the results are still slightly off. Anyone got an idea why?
 * Let me know, please.
 */
public class Converter {

    public static double[] Rgb2Lab(int[] rgb_) {
        double[] lab = {0, 0, 0};
        double[] xyz = {0, 0, 0};
        double[] rgb={0,0,0};
        rgb[0]=(double) rgb_[0];
        rgb[1]=(double) rgb_[1];
        rgb[2]=(double) rgb_[2];
        //RGB to xyz

        for (int i = 0; i < 3; i++) {
            rgb[i] = rgb[i] / 255;
        }

        if (rgb[0] > 0.04045) {
            xyz[0] = (double) Math.pow(((rgb[0] + 0.055) / 1.055), 2.4);
        } else {
            xyz[0] = (double) (rgb[0] / 12.92);
        }
 
        if (rgb[1] > 0.04045) {
            xyz[1] = (double) Math.pow(((rgb[1] + 0.055) / 1.055), 2.4);
        } else {
            xyz[1] = (double) (rgb[1] / 12.92);
        }
        if (rgb[2] > 0.04045) {
            xyz[2] = (double) Math.pow(((rgb[2] + 0.055) / 1.055), 2.4);
        } else {
            xyz[2] = (double) (rgb[2] / 12.92);
        }
        for (int i = 0; i < 3; i++) {
            xyz[i] = xyz[i] * 100;
        }

        //D65
        xyz[0] = (double) (xyz[0] * 0.4124 + xyz[1] * 0.3576 + xyz[2] * 0.1805);
        xyz[1] = (double) (xyz[0] * 0.2126 + xyz[1] * 0.7152 + xyz[2] * 0.0722);
        xyz[2] = (double) (xyz[0] * 0.0193 + xyz[1] * 0.1192 + xyz[2] * 0.9505);


        //XYZ to CieLab
        
        final double rx=95.047;
        final double ry=100.;
        final double rz=108.883;
        double l,a,b;
        
        //Illuminant= D65;
        lab[0]=xyz[0]/rx; 
        lab[1]=xyz[1]/ry;
        lab[2]=xyz[2]/rz;

        if (lab[0] > 0.008856) {
            lab[0] = Math.pow(lab[0], (1./3.));
        } else {
            lab[0] = (7.787 * lab[0]) + (16./116.);
        }
                  
        if (lab[1] > 0.008856) {
            lab[1] = Math.pow(lab[1], (1./3.));

        } else {
            lab[1] = (7.787 * lab[1]) + (16./116.);
        }
        if (lab[2] > 0.008856) {
            lab[2] = Math.pow(lab[2], (1./3.));
        } else {
            lab[2] = (7.787 * lab[2]) + (16./116.);
        }

        l = (116 * lab[1]) - 16;
        a = 500 * (lab[0] - lab[1]);
        b = 200 * (lab[1] - lab[2]);
        lab[0]=l;
        lab[1]=a+.8;
        lab[2]=b+.8;
    return lab;
    }

    public static String getHex(int pixel) {
        int red = (pixel >> 16) & 0xff;
        int green = (pixel >> 8) & 0xff;
        int blue = (pixel) & 0xff;
        Color color = new Color(red, green, blue);
        return colorToHex(color);
    }
    
    public static String colorToHex(Color y) {
        String[] tempArray = {"ff", "ff", "ff"};
        tempArray[0] = Integer.toString(y.getRed(), 16);
        tempArray[1] = Integer.toString(y.getGreen(), 16);
        tempArray[2] = Integer.toString(y.getBlue(), 16);
        for (int i = 0; i < 3; i++) {
            if (tempArray[i].length() == 0) {
                tempArray[i] = new StringBuffer(tempArray[i]).insert(0, "00").toString();
            } else if (tempArray[i].length() == 1) {
                tempArray[i] = new StringBuffer(tempArray[i]).insert(0, "0").toString();
            }
        }
        return tempArray[0] + tempArray[1] + tempArray[2];
    }
    
    public static double[] rgbString2LabDouble(String colorString){
        int[] intColor={0};
        int r=Integer.valueOf(colorString.substring(0, 2), 16);
        int g=Integer.valueOf(colorString.substring(2, 4), 16);
        int b=Integer.valueOf(colorString.substring(4, 6), 16);
        intColor[0]=r;
        intColor[1]=g;
        intColor[2]=b;
        return Rgb2Lab(intColor);        
    }
    
    public static String[][] getRGBColorStrings(BufferedImage screen, int[] excludeRange, int scanResolution) {
        String[][] colors = {};
        int pixel;
        int height = screen.getHeight() - excludeRange[0];
        int width = screen.getWidth() - excludeRange[1];
        for (int i = 0; i < width; i += scanResolution) {
            for (int j = 0; j < height; j += scanResolution) {
                pixel = screen.getRGB(i, j);
                colors[i][j] = getHex(pixel);
            }
        }
        return colors;
    }
}
